import cv2
import os
from sklearn import preprocessing
from sklearn import  decomposition
import numpy as np
import time
from collections import defaultdict
# 首先我们要加载图片的地址与类别
imgpath=[]
labels=[]
path='./faces/train/'
allperson=os.listdir(path)
for i in allperson:
    thisperson=os.listdir(os.path.join(path,i))
    for j in thisperson:
        thisimg=os.path.join(path,i,j)
        imgpath.append(thisimg)
        labels.append(str(i))
# 将类别进行数字化
plabel=preprocessing.LabelEncoder()
plabel.fit(labels)
intlabels=[int(plabel.transform([i])[0])for i in labels]
# 加载图片
train_img=[]
train_labels=[]
face=cv2.CascadeClassifier('./haarcascade_frontalface_alt.xml')
n=0
for i in imgpath:
    img=cv2.imread(i)
    img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    face_area=face.detectMultiScale(img_gray,1.5,5)
    for (x,y,w,h) in face_area:
        thisface=img_gray[y:y+h,x:x+w]
        train_img.append(thisface)
        thislabel=intlabels[n]
        train_labels.append(thislabel)
    n+=1
# 为了使得长度是统一的可以进行PCA降维，到统一的一个维度
train_img2=[]
for i in range(0,len(train_img)):
    pca=decomposition.PCA()
    # ft1=pca.fit(train_img[i])
    # ft1=pca.explained_variance_
    # #进行有效特征数的估计
    # ft2_num=len(np.where(ft1>0.6)[0])
    # print(ft2_num)
    pca.n_components=67
    thisimgft=pca.fit_transform(train_img[i])
    train_img2.append(thisimgft)



# 基于摄像头进行识别  解决准确率的问题
font=cv2.FONT_HERSHEY_COMPLEX
rec=cv2.face.LBPHFaceRecognizer_create()
train_labels=np.array(train_labels)
rec.train(train_img2,train_labels)
cap=cv2.VideoCapture(0)
# 创建一个字典进行计数
predict=defaultdict(int)
# 求1000次识别成功的准确率
for i in range(1000):
    ret,img=cap.read()
    img=cv2.resize(img,None,fx=1,fy=1)
    img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    face_area=face.detectMultiScale(img,1.5,5)
    for (x,y,w,h) in face_area:
        res,b=rec.predict(img_gray[y:y+h,x:x+w])
#         转文字
        rst2=plabel.inverse_transform([res])[0]
        # 将计数加上1
        predict[rst2]+=1
        print("这个人是:"+str(rst2))
        cv2.putText(img,str(rst2),(20,20),font,1,(0,0,255),1,False)
    cv2.imshow('img',img)
    key=cv2.waitKey(1)
    if key==ord('q'):
        break
# 对字典进行排序
sorted(predict.items(),key=lambda item:item[1],reverse=True)
maxacc=int(list(predict.items())[0][1])/1000
if maxacc>=0.92:
    print('验证合格，可以通过')
else:
    print('没有识别成功')






# # 基于测试图片进行识别
# rec=cv2.face.LBPHFaceRecognizer_create()
# train_labels=np.array(train_labels)
# print(train_img2[0].shape)
# rec.train(train_img2,train_labels)
# path2="./faces/test/"
# alltests=os.listdir(path2)
# font = cv2.FONT_HERSHEY_TRIPLEX
# for i in alltests:
#     thisimg=path2+str(i)
#     img=cv2.imread(thisimg)
#     img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#     face_area=face.detectMultiScale(img,1.5,5)
#     for (x,y,w,h) in face_area:
#         rst,b=rec.predict(img_gray[y:y+h,x:x+w])
#         cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),1)
#     #转文字
#     rst2=plabel.inverse_transform([rst])[0]
#     print(i)
#     print("这个人是："+str(rst2))
#     #cv2.putText(
#     cv2.putText(img, str(rst2),(20,20), font, 1, (0, 0, 255), 1,False)
#     cv2.imshow("img",img)
#     cv2.waitKey(1)
#     time.sleep(3)
#
